package com.mirabelle.juice.dao;

import java.io.Serializable;
import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.PersistenceUnit;
import javax.persistence.TypedQuery;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Root;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Repository;

import com.mirabelle.juice.model.Author;

@Repository("AuthorDao")
public class AuthorDaoImpl implements AuthorDao, Serializable {
	private static final long	serialVersionUID	= 1L;
	private transient Logger	log					= LoggerFactory.getLogger(getClass());
	
	@PersistenceUnit(unitName = "juiceUnit")
	private transient EntityManagerFactory	emf;
	
	@Override
	public List<Author> getAll() {
		EntityManager em = emf.createEntityManager();
		log.debug("Envoie de la requette de recherche des auteurs");
		
		CriteriaBuilder b = em.getCriteriaBuilder();
		CriteriaQuery<Author> q = b.createQuery(Author.class);
		Root<Author> root = q.from(Author.class);
		q.select(root);
		TypedQuery<Author> query = em.createQuery(q);
		List<Author> a = null;
		a = query.getResultList();
		
		em.close();
		return a;
	}

	@Override
	public Author getOneByMail(String mail) {
		EntityManager em = emf.createEntityManager();
		log.debug("Envoie de la requette de recherche de l'auteur pour le mail : " + mail);
		
		CriteriaBuilder b = em.getCriteriaBuilder();
		CriteriaQuery<Author> q = b.createQuery(Author.class);
		Root<Author> root = q.from(Author.class);
		q.where(b.equal(root.<String> get("mail"), mail));
		TypedQuery<Author> query = em.createQuery(q);
		Author a = null;
		try {
			a = query.setMaxResults(1).getSingleResult();
		} catch (Exception e) {
			log.debug(e.getMessage());
		}
		
		if (null != a) {
			log.debug("Auteur trouvé pour le mail : " + mail);
			em.refresh(a);
		} else {
			log.debug("Auteur intouvable pour le mail : " + mail);
		}
		em.close();
		return a;
	}
	
	@Override
	public Author getOneByNickName(String nickName) {
		EntityManager em = emf.createEntityManager();
		log.debug("Envoie de la requette de recherche de l'auteur pour le pseudo : " + nickName);
		
		CriteriaBuilder b = em.getCriteriaBuilder();
		CriteriaQuery<Author> q = b.createQuery(Author.class);
		Root<Author> root = q.from(Author.class);
		try {
			q.where(b.equal(root.<String> get("nickName"), nickName));
		} catch (Exception e) {
			log.debug(e.getMessage());
		}
		TypedQuery<Author> query = em.createQuery(q);
		Author a = null;
		try {
			a = query.setMaxResults(1).getSingleResult();
		} catch (Exception e) {
			log.debug(e.getMessage());
		}
		
		if (null != a) {
			log.debug("Auteur trouvé pour le pseudo : " + nickName);
			em.refresh(a);
		} else {
			log.debug("Auteur intouvable pour le pseudo : " + nickName);
		}
		em.close();
		return a;
	}

	@Override
	public Author getOne(int id) {
		EntityManager em = emf.createEntityManager();
		log.debug("Envoie de la requette de recherche du rôle pour l'identifiant : " + id);
		Author a = em.find(Author.class, id);
		if (null != a) {
			log.debug("Auteur trouvé pour l'identifiant : " + id);
		} else {
			log.debug("Auteur introuvable pour l'identifiant : " + id);
		}
		em.close();
		return a;
	}
	
	@Override
	public void saveAuthor(Author author) {
		EntityManager em = emf.createEntityManager();
		em.getTransaction().begin();
		if ((null != author.getId())&&(null != getOne(author.getId()))) {
			log.debug("Envoie de la requette de modification de l'auteur pour l'identifiant : " + author.getId());
			em.merge(author);
		} else {
			log.debug("Envoie de la requette de création de l'auteur pour l'identifiant : " + author.getId());
			em.persist(author);
		}
		em.getTransaction().commit();
		em.close();
	}
	
	@Override
	public void reload(Author author) {
		EntityManager em = emf.createEntityManager();
		em.refresh(em.merge(author));
	}
}

	
